/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.demo.service.impl;

import com.demo.dao.AccountDao;
import com.demo.exception.RestException;
import com.demo.model.Account;
import com.demo.model.Role;
import com.demo.service.AccountService;
import com.demo.service.RoleService;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

/**
 *
 * @author student
 */
@Service("accountService")
public class AccountServiceImpl implements AccountService {

    private final String error1 = "You can not get Model before you created it. Run Post in first.";
    
    @Resource(name = "accountDao")
    private AccountDao accountDao;
    
    @Resource(name = "roleService")
	private RoleService roleService;
    
    @Override
    public Account get(long id) throws RestException {
        Account item = null;
        item = accountDao.get(id);
        if (item == null) {
            throw new RestException(error1);
        }
        return item;
    }
    
    @Override
    public Account put(
            long id, 
            String email, 
            String fname, 
            String lname, 
            String zip, 
            String gender,
            long role
            ) throws RestException {
        Account item = accountDao.get(id);
        if (item == null) {
            throw new RestException(error1);
        }
        item.setEmail(email);
        item.setFirstName(fname);
        item.setLastName(lname);
        item.setZip(zip);
        item.setGender(gender);
        
        return save(item, role);
    }
    
    @Override
    public Account post(
            String email, 
            String fname, 
            String lname, 
            String zip, 
            String gender,
            long role
            ) throws RestException {
        
        Account item = new Account();
        item.setEmail(email);
        item.setFirstName(fname);
        item.setLastName(lname);
        item.setZip(zip);
        item.setGender(gender);
        
        
        
        return save(item, role);
    }
    
    private Account save(Account item, long role) throws RestException {
        Account account;
        try {
        
            Role ritem = roleService.get(role);        
            Set<Role> roles = new HashSet<Role>();
            roles.add(ritem);
            item.setRoles(roles);
        
            //item.setRole(ritem);
			account =  accountDao.save(item);
            
		} catch (Exception e) {
            throw new RestException(error1);
        }
        return account;
    }
    
    @Override
    public boolean delete(long id) throws RestException {
        Account item = accountDao.get(id);
        accountDao.remove(id);
        return true;
    }

	@Override
	public List list() throws RestException {
		return accountDao.getAll();
	}

    /*
     * 
     */
    @Override
    public boolean hasRole(ArrayList<String> roles) {
        try {
			Collection<GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();

			for (GrantedAuthority auth : authorities) {
				for (String role : roles) {
					if (auth.getAuthority().equals(role)) {
						return true;
					}
				}
			}
		} catch (NullPointerException e) {
		}

		return false;
    }
    
    @Override
    public boolean hasOneRole(String role) {
        ArrayList<String> roles = new ArrayList<String>();
		roles.add(role);
		return hasRole(roles);
    }

    @Override
    public void setRole(Account account, String roleName) {
        //remove old roles
		/*List<Role> oroles = roleService.getByAccount(account);
		for (Role orole : oroles) {
			roleService.remove(orole.getId());
		}
        */

		//add new role
		Role role = new Role();
		role.setRoleValue(roleName);
		role.setAcc(account);
		role = roleService.save(role);

		//add role to account
		Set<Role> roles = new HashSet<Role>();
		roles.add(role);
		account.setRoles(roles);
        accountDao.save(account);
		//save(account);
    }

    @Override
    public String getRole() {
        try {
			List<GrantedAuthority> authorities = 
                    (List<GrantedAuthority>) SecurityContextHolder.getContext().
                    getAuthentication().getAuthorities();
			if (authorities.isEmpty()) {
				return "ROLE_ANONYMOUS";
			} else {
				return authorities.get(0).getAuthority();
			}
		} catch (Exception ex) {
			return "ROLE_ANONYMOUS";
		}
    }

    /*
     * 
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        return getAccountByLogin(username);
    }

    /*
     * 
     */
    @Override
    public Account setAuthentication(String user, String password, Collection<GrantedAuthority> authorities) {
        SecurityContextHolder.getContext().setAuthentication(
				new UsernamePasswordAuthenticationToken(user, password, authorities));
		return null;
    }

    /*
     * 
     */
    /*@Override
    public Account getLoggedInAccount() {
        Account account = null;

		try {
			Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
			String username = "";
			
			if (principal instanceof UserDetails) {
				username = ((UserDetails) principal).getUsername();
			} else {
				username = principal.toString();
			}

			account = this.getAccountByLogin(username);

			Collection<GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();

			System.out.println(authorities.toString());

			return account;
		} catch (ClassCastException cce) {
			return (Account) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		} catch (NullPointerException ex) {
			return null;
		}
    }
    */

    @Override
    public Account getAccountByLogin(String login) {
        Account account = accountDao.getAccountByLogin(login);
		return account;
    }

    
    
}
